package com.xbongbong.workflow.upgrade;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.formula.constant.Constant;
import com.xbongbong.paas.config.enums.WorkflowTriggerMethodEnum;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.BusinessRuleInfoEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.RuleOperationEnum;
import com.xbongbong.paas.field.FilterConditionsPoJo;
import com.xbongbong.paas.field.FormulaPoJo;
import com.xbongbong.paas.model.BusinessRuleInfoModel;
import com.xbongbong.paas.model.PaasProcessMigrationModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.OperationsPojo;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.pojo.workflow.settings.ConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowNodeConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowAddDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowEnableDTO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowAddVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowEnableVO;
import com.xbongbong.paas.service.workflow.setting.WorkflowSetService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.domain.entity.PaasProcessMigrationEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.businessrule.enums.RuleValueTypeEnum;
import com.xbongbong.pro.enums.businessrule.enums.RuleVersionEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.pro.enums.workflow.WorkflowValueTypeEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowConditionOperatorEnum;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.pojo.FilterCondition;
import com.xbongbong.workflow.pojo.WorkflowNodeCoreConfiguration;
import com.xbongbong.workflow.pojo.WorkflowOperationsPojo;
import com.xbongbong.workflow.pojo.nodes.ApprovalNode;
import com.xbongbong.workflow.pojo.nodes.CcNode;
import com.xbongbong.workflow.pojo.nodes.ConditionBlockNode;
import com.xbongbong.workflow.pojo.nodes.ConditionNode;
import com.xbongbong.workflow.pojo.nodes.DeleteRecordNode;
import com.xbongbong.workflow.pojo.nodes.FormTriggerNode;
import com.xbongbong.workflow.pojo.nodes.InsertRecordNode;
import com.xbongbong.workflow.pojo.nodes.ObtainMultiDataNode;
import com.xbongbong.workflow.pojo.nodes.UpdateRecordNode;
import com.xbongbong.workflow.pojo.nodes.WorkflowConditionFilters;
import com.xbongbong.workflow.pojo.nodes.WorkflowConditionPojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowJointConditionPojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowNodePojo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * @author 吴峰
 * @date 2021/06/11 11:04
 */
@Component
@Slf4j
public class BusinessRuleUpgradeWorkflowHelp {

    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessRuleUpgradeWorkflowHelp.class);

    @Resource
    private BusinessRuleInfoModel businessRuleInfoModel;
    @Resource
    @Lazy
    private WorkflowSetService workFlowSetService;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private PaasProcessMigrationModel paasProcessMigrationModel;

    /**
     * 将业务规则转化到工作流中
     * @param formIdIn
     * @param baseDTO
     * @throws XbbException
     */
    public void upgradeBusinessRule(Map<Long, Integer> formIdIn, BaseDTO baseDTO) throws XbbException {
        try {
            if (Objects.isNull(formIdIn) || formIdIn.isEmpty()) {
                return;
            }
            String corpid = baseDTO.getCorpid();
            for (Map.Entry<Long, Integer> entry : formIdIn.entrySet()) {
                Long key = entry.getKey();
                Integer value = entry.getValue();
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put(StringConstant.FORM_ID, key);
                param.put(StringConstant.BUSINESS_TYPE, value);
                param.put(ParameterConstant.ORDER_BY_STR, "priority ASC");
                List<BusinessRuleInfoEntity> businessRuleInfoList = businessRuleInfoModel.findEntitys(param);
                if (CollectionsUtil.isNotEmpty(businessRuleInfoList)) {
                    insertRuleList(businessRuleInfoList, baseDTO);
                }
            }
        } catch (Exception e) {
            LOGGER.error("BusinessRuleUpgradeWorkflowHelp.upgradeBusinessRule error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 将业务规则插入到工作流节点的后面
     * @param formIdIn
     * @param baseDTO
     * @throws XbbException
     */
    public void processUpgradeBusinessRule(Map<Long, Integer> formIdIn, BaseDTO baseDTO, Map<Long, PaasFormEntity> formMap, Map<Long, WorkOrderFormEntity> workOrderFormMap) throws XbbException {
        try {
            if (Objects.isNull(formIdIn) || formIdIn.isEmpty()) {
                return;
            }
            String corpid = baseDTO.getCorpid();
            for (Map.Entry<Long, Integer> entry : formIdIn.entrySet()) {
                Long key = entry.getKey();
                Integer value = entry.getValue();
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put(StringConstant.BUSINESS_TYPE, value);
                param.put(StringConstant.FORM_ID, key);

                List<PaasProcessTemplateEntityExt> processTemplateList = paasProcessTemplateModel.list(param);
                if (CollectionsUtil.isNotEmpty(processTemplateList)) {
                    // 再无启用流程的情况下，获取最后一次更新的未启用流程，需要用来作为当前版本
                    PaasProcessTemplateEntityExt lastProcess = getLastProcessTemplate(processTemplateList);
                    String version = UUID.randomUUID().toString();
                    Integer allowEditAfterFinish = 0;
                    long now = DateTimeUtil.getInt();
                    List<PaasProcessMigrationEntity> processMigrationList = new ArrayList<>();
                    for(PaasProcessTemplateEntityExt processTemplate: processTemplateList){
                        if (Objects.equals(processTemplate.getAllowEditAfterFinished(), 1)) {
                            allowEditAfterFinish = 1;
                        }
                        // 获取需审批字段
                        List<String> needApproveFieldList = processTemplate.getNeedApproveFieldList();
                        // 获取触发方式
                        Integer triggerEventType = getTriggerEventType(processTemplate);
                        Integer currentVersion = 0;
                        if (Objects.equals(1, processTemplate.getEnable())) {
                            currentVersion = 1;
                        }
                        if (Objects.nonNull(lastProcess) && Objects.equals(lastProcess.getId(), processTemplate.getId())) {
                            currentVersion = 1;
                        }
                        String name;
                        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), processTemplate.getBusinessType())) {
                            if (!workOrderFormMap.containsKey(processTemplate.getFormId())) {
                                // 删掉的表单，无需迁移模板
                                continue;
                            }
                            name = workOrderFormMap.get(processTemplate.getFormId()).getName();
                        } else {
                            if (!formMap.containsKey(processTemplate.getFormId())) {
                                // 删掉的表单，无需迁移模板
                                continue;
                            }
                            name = formMap.get(processTemplate.getFormId()).getName();
                        }
                        name = name + "审批（迁移）";
                        WorkflowEntity workflowEntity = new WorkflowEntity(corpid, "", name, version, WorkflowTriggerMethodEnum.FORM.getType(), triggerEventType, processTemplate.getAppId(),
                                processTemplate.getFormId(),  processTemplate.getMenuId(), processTemplate.getSaasMark(), Objects.isNull(processTemplate.getBusinessType()) ? 0 : processTemplate.getBusinessType(),
                                1, processTemplate.getEnable(), 1, processTemplate.getUpdateTime(), processTemplate.getAllowWithdraw(), processTemplate.getAllowViewLog(), Constant.ZERO,processTemplate.getEmptyApproverType(), processTemplate.getVersionName(), processTemplate.getVersionId(), currentVersion,
                                processTemplate.getUsePermission(), processTemplate.getApproverDeduplication(), processTemplate.getAutomaticallyApprovedSponsor(), processTemplate.getIsArchive(), processTemplate.getCreatorId(),processTemplate.getRolesWithoutApprove());
                        if (Objects.equals(processTemplate.getSaasMark(), SaasMarkEnum.PAAS.getCode()) && Objects.isNull(workflowEntity.getBusinessType())) {
                            // 可能有脏数据
                            workflowEntity.setBusinessType(0);
                        }

                        workflowModel.insert(workflowEntity);
                        List<PaasProcessTemplateNodeEntityExt> nodeList = paasProcessTemplateNodeModel.getNodeByTemplateIdList(processTemplate.getId(), corpid);
                        List<WorkflowNodeEntityExt> workflowNodeList = new ArrayList<>();
                        WorkflowNodeEntityExt startNode = null;
                        for (PaasProcessTemplateNodeEntityExt templateNode : nodeList) {
                            if (Objects.equals(templateNode.getType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType())) {
                                // 开始节点需要单独处理
                                FormTriggerNode formTriggerNode = new FormTriggerNode();
                                formTriggerNode.setType(triggerEventType);
                                formTriggerNode.setNeedApproveFields(needApproveFieldList);
                                Map<String, FieldPermissionEntityExt> fieldPermissionMap = getFieldPermissionMap(templateNode.getFieldPermissionList());
                                formTriggerNode.setFieldPermission(fieldPermissionMap);
                                String configData = JSON.toJSONString(formTriggerNode);
                                startNode = new WorkflowNodeEntityExt(corpid, templateNode.getName(), WorkflowTriggerMethodEnum.FORM.getType(), templateNode.getType(), templateNode.getAppId(), templateNode.getFormId(), templateNode.getMenuId(),
                                        processTemplate.getSaasMark(), processTemplate.getBusinessType(), workflowEntity.getId(), templateNode.getUid(), templateNode.getPrevId(), templateNode.getWrapperId(), templateNode.getPriority(), configData, templateNode.getId());
                                break;
                            }
                        }
                        workflowNodeModel.insert(startNode);
                        for (PaasProcessTemplateNodeEntityExt node : nodeList) {
                            String configData = "{}";
                            if (Objects.equals(node.getType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType())) {
                                continue;
                            } else if (Objects.equals(NodeTypeEnum.PROCESS_NODE.getNodeType(), node.getType())) {
                                Map<String, FieldPermissionEntityExt> fieldPermissionMap = getFieldPermissionMap(node.getFieldPermissionList());
                                ApprovalNode approvalNode = new ApprovalNode(fieldPermissionMap, node.getMainUserList(), node.getEnableCCFlag(), node.getCcUserList(), node.getOpinionFlag(),
                                        node.getCommitFlag(), node.getCommitText(), node.getStorageFlag(), node.getStorageText(), node.getCommitPrintFlag(), node.getCommitPrintText(),
                                        node.getBackFlag(), node.getBackType(), node.getBackText(), node.getBackNode(), node.getTransferFlag(), node.getTransferText(), node.getTransferUserList(),
                                        node.getEndFlag(), node.getEndText(), node.getCommitVerifyFlag(), JSON.parseArray(node.getCommitVerifyCondition()), node.getSignType(), node.getTimeoutHandle(), node.getPrintTemplateId(),
                                        node.getCcPrintFlag(), WorkflowNodeUtil.getDefaultTitleList());
                                configData = JSON.toJSONString(approvalNode);
                            } else if (Objects.equals(NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType(), node.getType())) {
                                configData = JSON.toJSONString(new ConditionBlockNode());
                            } else if (Objects.equals(NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType(), node.getType())) {

                                WorkflowJointConditionPojo workflowJointConditionPojo = new WorkflowJointConditionPojo();
                                workflowJointConditionPojo.setOperator(WorkflowConditionOperatorEnum.AND.getAlias());

                                List<WorkflowConditionFilters> filters = new ArrayList<>();
                                WorkflowConditionFilters workflowConditionFilters = new WorkflowConditionFilters();
                                workflowConditionFilters.setOperator(WorkflowConditionOperatorEnum.AND.getAlias());

                                List<WorkflowConditionPojo> list = new ArrayList();
                                if (CollectionsUtil.isNotEmpty(node.getConditions())) {
                                    for (ConditionsEntityExt item : node.getConditions()) {
                                        WorkflowConditionPojo workflowConditionPojo = new WorkflowConditionPojo(item.getFieldType(), item.getAttr(), 1, startNode.getId(), startNode.getFormId(),
                                                startNode.getSaasMark(), startNode.getBusinessType(), item.getSymbol(), WorkflowValueTypeEnum.FIXED_VALUE.getType(), item.getValue());
                                        list.add(workflowConditionPojo);
                                    }
                                }

                                workflowConditionFilters.setFilter(list);

                                filters.add(workflowConditionFilters);

                                workflowJointConditionPojo.setFilters(filters);


                                ConditionNode conditionNode = new ConditionNode(node.getConditionType(), workflowJointConditionPojo, ConditionTypeEnum.GENERAL_CONDITION.getType(), 1);
                                configData = JSON.toJSONString(conditionNode);
                            } else if (Objects.equals(NodeTypeEnum.CC_PROCESS_NODE.getNodeType(), node.getType())) {
                                Map<String, FieldPermissionEntityExt> fieldPermissionMap = getFieldPermissionMap(node.getFieldPermissionList());
                                CcNode ccNode = new CcNode(node.getCcUserList(), fieldPermissionMap, WorkflowNodeUtil.getDefaultTitleList());
                                configData = JSON.toJSONString(ccNode);
                            }
                            WorkflowNodeEntityExt workflowNodeEntity = new WorkflowNodeEntityExt(corpid, node.getName(), WorkflowTriggerMethodEnum.FORM.getType(), node.getType(), node.getAppId(), node.getFormId(), node.getMenuId(),
                                    processTemplate.getSaasMark(), processTemplate.getBusinessType(), workflowEntity.getId(), node.getUid(), node.getPrevId(), node.getWrapperId(), node.getPriority(), configData, node.getId());
                            workflowNodeList.add(workflowNodeEntity);
                        }
                        workflowNodeModel.insertExtBatch(workflowNodeList);
                        workflowNodeList.add(startNode);
                        // 以审批节点id为key，工作流节点id为value的集合
                        JSONObject processNodeAndWorkflowNodeMap = new JSONObject();
                        workflowNodeList.forEach(item->processNodeAndWorkflowNodeMap.put(item.getProcessNodeId().toString(), item.getId()));
                        // 记录迁移模板
                        PaasProcessMigrationEntity paasProcessMigrationEntity = new PaasProcessMigrationEntity(corpid, processTemplate.getFormId(), processTemplate.getSaasMark(), processTemplate.getBusinessType(), processTemplate.getId(), processTemplate.getEnable(), workflowEntity.getId(), processNodeAndWorkflowNodeMap, baseDTO.getUserId(), now, now, DelEnum.NORMAL.getDel());
                        processMigrationList.add(paasProcessMigrationEntity);

                    }
                    paasProcessMigrationModel.insertBatch(processMigrationList);

                    Integer saasMark = SaasMarkEnum.SAAS.getCode();
                    if (Objects.equals(0, value)) {
                        saasMark = SaasMarkEnum.PAAS.getCode();
                    }
                    workFlowSetService.saveAllowEditAfterFinished(corpid, key, saasMark, value, allowEditAfterFinish);

                }

            }
        } catch (Exception e) {
            LOGGER.error("BusinessRuleUpgradeWorkflowHelp.processUpgradeBusinessRule error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
    /**
     *
     * 获取没有启用的版本：
     * 1. 流程版本中可能会存在多个含有流程任务的版本，那么是不是可以以更新时间最后一个的含有流程任务的版本作为当前版本；
     * 2. 流程版本中没有流程任务的版本，那么就以更新时间最新的那个版本作为当前版本；
     */
    private PaasProcessTemplateEntityExt getLastProcessTemplate(List<PaasProcessTemplateEntityExt> processTemplateList) {

        PaasProcessTemplateEntityExt lastProcess = null;
        Integer enable = 0;
        for (PaasProcessTemplateEntityExt paasProcessTemplateEntityExt : processTemplateList) {
            if (Objects.equals(0, paasProcessTemplateEntityExt.getEnable())) {
                if (lastProcess == null) {
                    lastProcess = paasProcessTemplateEntityExt;
                } else if (paasProcessTemplateEntityExt.getUpdateTime() > lastProcess.getUpdateTime()) {
                    lastProcess = paasProcessTemplateEntityExt;
                }
            } else {
                enable = paasProcessTemplateEntityExt.getEnable();
                break;
            }
        }
        if (enable == 1) {
            lastProcess = null;
        }
        return lastProcess;
    }

    /**
     * 将list转成map
     * @param list
     * @return
     */
    private Map<String, FieldPermissionEntityExt> getFieldPermissionMap(List<FieldPermissionEntityExt> list) {
        Map<String, FieldPermissionEntityExt> fieldPermissionMap = new HashMap<>(list.size());
        list.forEach((item)->{
            String attr = item.getAttr();
            if (StringUtil.isNotEmpty(item.getSubAttr())) {
                attr = attr + StringConstant.POINT + item.getSubAttr();
            }
            fieldPermissionMap.put(attr, item);
        });
        return fieldPermissionMap;
    }

    private Integer getTriggerEventType(PaasProcessTemplateEntityExt processTemplateEntityExt) {
        Integer triggerEventType = TriggerEventTypeEnum.ONLY_ADD.getType();
        if (CollectionsUtil.isNotEmpty(processTemplateEntityExt.getNeedApproveFieldList())) {
            triggerEventType = TriggerEventTypeEnum.ADD_OR_UPDATE.getType();
        }
        return triggerEventType;
    }
    /**
     * 获取起始节点和最后一个节点uid
     * @param workflowNodeList
     * @return
     */
    private WorkflowAddVO getStartNodeAndLastNode( List<WorkflowNodeEntity> workflowNodeList, WorkflowNodeEntity startNode) {
        WorkflowAddVO workflowAddVO = new WorkflowAddVO();
        Long workflowNodeId = startNode.getId();
        String uid = startNode.getUid();
        uid = findLastNode(workflowNodeList, uid);
        workflowAddVO.setLastUid(uid);
        workflowAddVO.setWorkflowNodeId(workflowNodeId);
        return workflowAddVO;
    }

    /**
     * 遍历到最后一个节点
     * @param workflowNodeList
     * @param uid
     * @return
     */
    private String findLastNode(List<WorkflowNodeEntity> workflowNodeList, String uid) {
        for (WorkflowNodeEntity item : workflowNodeList) {
            if (Objects.equals(item.getPrevId(), uid) && Objects.isNull(item.getWrapperId())) {
                uid = item.getUid();
            }
        }
        return uid;
    }


    private void processInsertRuleList(List<BusinessRuleInfoEntity> businessRuleList, WorkflowAddVO workflowAddVO) throws XbbException{
        // 将生效规则转化为节点
        getProcessActiveNodeList(workflowAddVO.getLastUid(), businessRuleList, workflowAddVO);
        // 先失效后生效
        insertProcessInactiveAndActiveRule(workflowAddVO.getLastUid(), businessRuleList, workflowAddVO);
        // 将失效规则转化为节点
        getProcessInactiveNodeList(businessRuleList, workflowAddVO);
    }

    private String insertProcessInactiveAndActiveRule(String prevId, List<BusinessRuleInfoEntity> businessRuleList, WorkflowAddVO workflowAddVO) throws XbbException{

        for (BusinessRuleInfoEntity item : businessRuleList) {
            if (!Objects.equals(1, item.getInactiveEnable())) {
                continue;
            }
            prevId = insertInactiveRule(prevId, item, workflowAddVO);
            if (!Objects.equals(1, item.getActiveEnable())) {
                continue;
            }
            prevId = insertActiveRule(prevId, item, workflowAddVO);
        }

        return prevId;
    }


    private void getProcessActiveNodeList( String prevId, List<BusinessRuleInfoEntity> businessRuleList, WorkflowAddVO workflowAddVO) throws XbbException {

        for (BusinessRuleInfoEntity item : businessRuleList) {
            if (!Objects.equals(1, item.getActiveEnable())) {
                continue;
            }
            prevId = insertActiveRule(prevId, item, workflowAddVO);
        }
    }


    private void getProcessInactiveNodeList(List<BusinessRuleInfoEntity> businessRuleList, WorkflowAddVO workflowAddVO) throws XbbException {

        String prevId = workflowAddVO.getLastUid();

        for (BusinessRuleInfoEntity item : businessRuleList) {
            if (!Objects.equals(1, item.getInactiveEnable())) {
                continue;
            }
            prevId = insertInactiveRule(prevId, item, workflowAddVO);
        }
    }

    private Map<Integer, List<WorkflowNodeEntity>> insertRuleList(List<BusinessRuleInfoEntity> businessRuleList, BaseDTO baseDTO) throws XbbException{
        Map<Integer, List<WorkflowNodeEntity>> nodeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 生效规则
        getActiveNodeList(businessRuleList, baseDTO);
        // 生效规则和失效规则
        getInactiveAndActiveNodeList(businessRuleList, baseDTO);
        // 失效规则
        getInactiveNodeList(businessRuleList, baseDTO);
        return nodeMap;
    }

    /**
     * 将失效和生效转化为工作流
     * @param businessRuleList
     * @param baseDTO
     * @throws XbbException
     */
    private void getInactiveAndActiveNodeList(List<BusinessRuleInfoEntity> businessRuleList, BaseDTO baseDTO) throws XbbException {

        String prevId = "startNode";
        BusinessRuleInfoEntity businessRuleInfoEntity = null;
        for (BusinessRuleInfoEntity ruleInfoEntity : businessRuleList) {
            if (Objects.equals(1, ruleInfoEntity.getInactiveEnable())) {
                businessRuleInfoEntity = ruleInfoEntity;
            }
        }
        if (Objects.isNull(businessRuleInfoEntity)) {
            return;
        }
        WorkflowAddVO workflowAddVO = addWorkflow(businessRuleInfoEntity, baseDTO, TriggerEventTypeEnum.ONLY_UPDATE.getType());
        for (BusinessRuleInfoEntity item : businessRuleList) {
            prevId = insertInactiveAndActiveRule(prevId, item, workflowAddVO);
        }
        enable(baseDTO, workflowAddVO);
    }


    private String insertInactiveAndActiveRule(String prevId, BusinessRuleInfoEntity businessRuleInfoEntity, WorkflowAddVO workflowAddVO) throws XbbException{
        prevId = insertInactiveRule(prevId, businessRuleInfoEntity, workflowAddVO);
        prevId = insertActiveRule(prevId, businessRuleInfoEntity, workflowAddVO);
        return prevId;
    }


    /**
     * 将失效规则转化为工作流
     * @param businessRuleList
     * @param baseDTO
     * @throws XbbException
     */
    private void getInactiveNodeList(List<BusinessRuleInfoEntity> businessRuleList, BaseDTO baseDTO) throws XbbException {

        String prevId = "startNode";
        BusinessRuleInfoEntity businessRuleInfoEntity = null;
        for (BusinessRuleInfoEntity ruleInfoEntity : businessRuleList) {
            if (Objects.equals(1, ruleInfoEntity.getInactiveEnable())) {
                businessRuleInfoEntity = ruleInfoEntity;
            }
        }
        if (Objects.isNull(businessRuleInfoEntity)) {
            return;
        }
        WorkflowAddVO workflowAddVO = addWorkflow(businessRuleInfoEntity, baseDTO, TriggerEventTypeEnum.ONLY_DELETE.getType());
        for (BusinessRuleInfoEntity item : businessRuleList) {
            if (!Objects.equals(1, item.getInactiveEnable())) {
                continue;
            }
            prevId = insertInactiveRule(prevId, item, workflowAddVO);
        }
        enable(baseDTO, workflowAddVO);
    }

    /**
     * 将失效的业务规则中的触发条件，过滤条件，操作进行拆分成条件节点，获取多条数据节点，新建/更新/删除节点
     * @param prevId
     * @param ruleInfo
     * @param workflowAddVO
     * @return
     * @throws XbbException
     */
    private String insertInactiveRule(String prevId, BusinessRuleInfoEntity ruleInfo, WorkflowAddVO workflowAddVO) throws XbbException{
        String wrapperUid = null;
        String corpid = ruleInfo.getCorpid();
        Integer operatorType = ruleInfo.getInactiveOperationType();
        Integer activeType = ruleInfo.getInactiveType();
        if (Objects.isNull(operatorType)) {
           return prevId;
        }
        List<FilterConditionsPoJo> preCondition = JSON.parseArray(ruleInfo.getInactivePreConditions(), FilterConditionsPoJo.class);
        if (CollectionsUtil.isNotEmpty(preCondition)) {
            // 1. 处理触发条件，转化为条件分支
            WorkflowNodeEntity workflowNodeEntity = insertPreCondition(corpid, prevId, preCondition, ruleInfo.getFormId(), ruleInfo.getSaasMark(), ruleInfo.getBusinessType(),
                    workflowAddVO);
            wrapperUid = workflowNodeEntity.getWrapperId();
            prevId = workflowNodeEntity.getUid();
        }
            // 2. 判断操作方式，将各个操作进行拆分成对应的节点；
        /**
         * 删除节点拆分为获取多条数据节点和删除数据节点；
         * 插入节点拆分为新建数据节点；
         * 更新节点拆分为获取多条数据节点和更新数据节点；
         * 更新和新建拆分为结果分支，有数据的条件则走更新数据节点，无结果的条件分支则走新建数据节点；
         */
        if (Objects.equals(RuleOperationEnum.ONLY_DELETE.getType(), operatorType)) {
            return insertDeleteNode(corpid, ruleInfo.getInactiveName(), ruleInfo.getInactiveFilterConditions(),
                    ruleInfo.getFormId(),ruleInfo.getBusinessType(), ruleInfo.getSaasMark(),
                    ruleInfo.getInactiveAppId(),
                    ruleInfo.getInactiveFormId(), ruleInfo.getInactiveMenuId(), ruleInfo.getInactiveBusinessType(), ruleInfo.getInactiveSaasMark(),
                    prevId, wrapperUid, workflowAddVO, ruleInfo.getInactiveMemo(), 0);
        } else if (Objects.equals(RuleOperationEnum.ONLY_INSERT.getType(), operatorType)){
            return insertAddNode(corpid, ruleInfo.getInactiveName(), ruleInfo.getInactiveOperations(), ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(),
                    ruleInfo.getInactiveAppId(),
                    ruleInfo.getInactiveFormId(), ruleInfo.getInactiveMenuId(), ruleInfo.getInactiveBusinessType(), ruleInfo.getInactiveSaasMark(),
                    prevId, wrapperUid, workflowAddVO, activeType, ruleInfo.getInactiveMemo(), null, 0);
        } else if (Objects.equals(RuleOperationEnum.ONLY_UPDATE.getType(), operatorType)) {
            return insertUpdateNode(corpid, ruleInfo.getInactiveName(), ruleInfo.getInactiveFilterConditions(), ruleInfo.getInactiveOperations(),
                    ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(), ruleInfo.getInactiveAppId(),
                    ruleInfo.getInactiveFormId(), ruleInfo.getInactiveMenuId(), ruleInfo.getInactiveBusinessType(),
                    ruleInfo.getInactiveSaasMark(), prevId, wrapperUid, workflowAddVO,
                    activeType, ruleInfo.getActiveMemo(), 0);

        }else if (Objects.equals(RuleOperationEnum.UPDATE_AND_INSERT.getType(), operatorType)) {
            return insertUpdateAndAddNode(corpid, ruleInfo.getInactiveName(), ruleInfo.getInactiveFilterConditions(), ruleInfo.getInactiveOperations(),
                    ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(), ruleInfo.getInactiveAppId(),
                    ruleInfo.getInactiveFormId(), ruleInfo.getInactiveMenuId(), ruleInfo.getInactiveBusinessType(),
                    ruleInfo.getInactiveSaasMark(), prevId, wrapperUid, workflowAddVO,
                    activeType, ruleInfo.getInactiveMemo(), 0);
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 将生效规则转化为工作流
     * @param businessRuleList
     * @param baseDTO
     * @throws XbbException
     */
    private void getActiveNodeList(List<BusinessRuleInfoEntity> businessRuleList, BaseDTO baseDTO) throws XbbException {

        String prevId = "startNode";

        BusinessRuleInfoEntity businessRuleInfoEntity = null;
        for (BusinessRuleInfoEntity ruleInfoEntity : businessRuleList) {
            if (Objects.equals(1, ruleInfoEntity.getActiveEnable())) {
                businessRuleInfoEntity = ruleInfoEntity;
            }
        }
        if (Objects.isNull(businessRuleInfoEntity)) {
            return;
        }
        WorkflowAddVO workflowAddVO = addWorkflow(businessRuleInfoEntity, baseDTO, TriggerEventTypeEnum.ONLY_ADD.getType());
        for (BusinessRuleInfoEntity item : businessRuleList) {
            if (!Objects.equals(1, item.getActiveEnable())) {
                continue;
            }
            prevId = insertActiveRule(prevId, item, workflowAddVO);
        }
        enable(baseDTO, workflowAddVO);
    }


    /**
     * 插入生效规则的相关节点
     * @param prevId
     * @param ruleInfo
     * @param workflowAddVO
     * @return
     * @throws XbbException
     */
    private String insertActiveRule(String prevId, BusinessRuleInfoEntity ruleInfo, WorkflowAddVO workflowAddVO) throws XbbException{
        String wrapperUid = null;
        String corpid = ruleInfo.getCorpid();
        Integer operatorType = ruleInfo.getActiveOperationType();
        Integer activeType = ruleInfo.getActiveType();
        if (Objects.isNull(operatorType)) {
            return prevId;
        }
        List<FilterConditionsPoJo> preCondition = JSON.parseArray(ruleInfo.getActivePreConditions(), FilterConditionsPoJo.class);
        if (CollectionsUtil.isNotEmpty(preCondition)) {
            WorkflowNodeEntity workflowNodeEntity = insertPreCondition(corpid, prevId, preCondition, ruleInfo.getFormId(), ruleInfo.getSaasMark(), ruleInfo.getBusinessType(),
                    workflowAddVO);
            wrapperUid = workflowNodeEntity.getWrapperId();
            prevId = workflowNodeEntity.getUid();
        }

        if (Objects.equals(RuleOperationEnum.ONLY_DELETE.getType(), operatorType)) {
            return insertDeleteNode(corpid, ruleInfo.getActiveName(), ruleInfo.getActiveFilterConditions(),
                    ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(), ruleInfo.getActiveAppId(),
                    ruleInfo.getActiveFormId(), ruleInfo.getActiveMenuId(), ruleInfo.getActiveBusinessType(), ruleInfo.getActiveSaasMark(),
                    prevId, wrapperUid, workflowAddVO, ruleInfo.getActiveMemo(), 1);
        } else if (Objects.equals(RuleOperationEnum.ONLY_INSERT.getType(), operatorType)){
            return insertAddNode(corpid, ruleInfo.getActiveName(), ruleInfo.getActiveOperations(), ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(),
                    ruleInfo.getActiveAppId(),
                    ruleInfo.getActiveFormId(), ruleInfo.getActiveMenuId(), ruleInfo.getActiveBusinessType(), ruleInfo.getActiveSaasMark(),
                    prevId, wrapperUid, workflowAddVO, activeType, ruleInfo.getActiveMemo(), null, 1);
        } else if (Objects.equals(RuleOperationEnum.ONLY_UPDATE.getType(), operatorType)) {

            return insertUpdateNode(corpid, ruleInfo.getActiveName(), ruleInfo.getActiveFilterConditions(), ruleInfo.getActiveOperations(),
                    ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(), ruleInfo.getActiveAppId(), ruleInfo.getActiveFormId(),
                    ruleInfo.getActiveMenuId(), ruleInfo.getActiveBusinessType(), ruleInfo.getActiveSaasMark(), prevId, wrapperUid, workflowAddVO,
                    activeType, ruleInfo.getActiveMemo(), 1);

        }else if (Objects.equals(RuleOperationEnum.UPDATE_AND_INSERT.getType(), operatorType)) {
            return insertUpdateAndAddNode(corpid, ruleInfo.getActiveName(), ruleInfo.getActiveFilterConditions(), ruleInfo.getActiveOperations(),
                    ruleInfo.getFormId(), ruleInfo.getBusinessType(), ruleInfo.getSaasMark(), ruleInfo.getActiveAppId(), ruleInfo.getActiveFormId(),
                    ruleInfo.getActiveMenuId(), ruleInfo.getActiveBusinessType(), ruleInfo.getActiveSaasMark(), prevId, wrapperUid, workflowAddVO,
                    activeType, ruleInfo.getActiveMemo(), 1);
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private WorkflowAddVO addWorkflow(BusinessRuleInfoEntity businessRuleInfoEntity, BaseDTO baseDTO, Integer triggerEventType) throws XbbException {
        WorkflowAddDTO workflowAddDTO = new WorkflowAddDTO();
        workflowAddDTO.setAppId(businessRuleInfoEntity.getAppId());
        workflowAddDTO.setMenuId(businessRuleInfoEntity.getMenuId());
        workflowAddDTO.setFormId(businessRuleInfoEntity.getFormId());
        workflowAddDTO.setSaasMark(businessRuleInfoEntity.getSaasMark());
        workflowAddDTO.setBusinessType(businessRuleInfoEntity.getBusinessType());
        workflowAddDTO.setType(WorkflowTriggerMethodEnum.FORM.getType());
        workflowAddDTO.setTriggerEventType(triggerEventType);
        workflowAddDTO.setName("未命名工作流");
        WorkflowNodePojo workflowNodePojo = getStartNode(businessRuleInfoEntity, triggerEventType);
        workflowAddDTO.setWorkflowNode(workflowNodePojo);
        workflowAddDTO.setLoginUser(baseDTO.getLoginUser());
        workflowAddDTO.setCorpid(baseDTO.getCorpid());
        workflowAddDTO.setUserId(baseDTO.getUserId());
        workflowAddDTO.setHttpHeader(baseDTO.getHttpHeader());
        workflowAddDTO.setLoginUserName(baseDTO.getLoginUserName());
        WorkflowAddVO workflowAddVO = workFlowSetService.add(workflowAddDTO);
        return workflowAddVO;
    }

    /**
     * 启用工作流
     * @param upgradeToWorkflowDTO
     * @param workflowAddVO
     * @throws XbbException
     */
    private void enable(BaseDTO upgradeToWorkflowDTO, WorkflowAddVO workflowAddVO) throws XbbException{
        WorkflowEnableDTO workflowEnableDTO = new WorkflowEnableDTO();
        workflowEnableDTO.setCorpid(upgradeToWorkflowDTO.getCorpid());
        workflowEnableDTO.setWorkflowId(workflowAddVO.getWorkflowId());
        workflowEnableDTO.setLoginUser(upgradeToWorkflowDTO.getLoginUser());
        workflowEnableDTO.setUserId(upgradeToWorkflowDTO.getUserId());
        workflowEnableDTO.setHttpHeader(upgradeToWorkflowDTO.getHttpHeader());
        workflowEnableDTO.setEnable(1);
        workflowEnableDTO.setLoginUserName(upgradeToWorkflowDTO.getLoginUserName());
        WorkflowEnableVO workflowEnableVO = workFlowSetService.enable(workflowEnableDTO);
        if (Objects.equals(workflowEnableVO.getSuccess(), 0)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     *
     * @param corpid
     * @param name
     * @param condition 过滤条件
     * @param operator 操作
     * @param formId 触发表单-表单id
     * @param businessType 触发表单-业务类型
     * @param saasMark 触发表单-saas标识
     * @param targetAppId 执行表单/目标表单-应用id
     * @param targetFormId 执行表单/目标表单-表单id
     * @param targetMenuId 执行表单/目标表单-菜单id
     * @param targetBusinessType 执行表单/目标表单-业务类型
     * @param targetSaasMark 执行表单/目标表单-saas标识
     * @param prevId 上一个节点uid
     * @param wrapperUid 当前节点属于的块uid
     * @param workflowAddVO
     * @param activeType 高级版还是简易版
     * @param memo
     * @return
     */
    private String insertUpdateAndAddNode(String corpid, String name, String condition, String operator, Long formId, Integer businessType, Integer saasMark,
                                          Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType,
                                          Integer targetSaasMark, String prevId, String wrapperUid, WorkflowAddVO workflowAddVO, Integer activeType, String memo, Integer editedData) {
        WorkflowNodeEntity dataNodeCondition =  getMultiDataNode(corpid, name, condition, formId, businessType, saasMark,  workflowAddVO.getWorkflowNodeId(), targetAppId, targetFormId, targetMenuId, targetBusinessType, targetSaasMark,
                workflowAddVO.getWorkflowId(), prevId, wrapperUid, editedData);
        workflowNodeModel.insert(dataNodeCondition);
        List<WorkflowNodeEntity> nodeList = new ArrayList<>();
        WorkflowNodeEntity wrapperNodeCondition = new WorkflowNodeEntity(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), dataNodeCondition.getUid(), wrapperUid, null, JSON.toJSONString(new JSONObject()));
        ConditionNode hasDataCondition = new ConditionNode();
        hasDataCondition.setConditions(new WorkflowJointConditionPojo());
        hasDataCondition.setType(ConditionTypeEnum.RESULT_CONDITION.getType());
        hasDataCondition.setConditionType(WorkflowNodeConditionTypeEnum.HAS_DATA.getType());
        WorkflowNodeEntity leftNodeCondition = new WorkflowNodeEntity(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), wrapperNodeCondition.getUid(),
                wrapperNodeCondition.getUid(), 1, JSON.toJSONString(hasDataCondition));
        ConditionNode noDataCondition = new ConditionNode();
        noDataCondition.setConditions(new WorkflowJointConditionPojo());
        noDataCondition.setType(ConditionTypeEnum.RESULT_CONDITION.getType());
        noDataCondition.setConditionType(WorkflowNodeConditionTypeEnum.NONE_DATA.getType());
        WorkflowNodeEntity rightNodeCondition = new WorkflowNodeEntity(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), wrapperNodeCondition.getUid(),
                wrapperNodeCondition.getUid(), 2, JSON.toJSONString(noDataCondition));
        nodeList.add(wrapperNodeCondition);
        nodeList.add(leftNodeCondition);
        nodeList.add(rightNodeCondition);

        WorkflowNodeEntity updateNode = getUpdateNode(corpid, dataNodeCondition.getId(), operator, formId, businessType, saasMark, workflowAddVO.getWorkflowNodeId(), activeType,
                name, targetAppId, targetFormId, targetMenuId, targetBusinessType, targetSaasMark, workflowAddVO.getWorkflowId(),
                leftNodeCondition.getUid(), leftNodeCondition.getWrapperId(), memo, dataNodeCondition, editedData);
        WorkflowNodeEntity insertNode = getInsertNode(corpid, operator, formId, businessType, saasMark, workflowAddVO.getWorkflowNodeId(), activeType,
                name, targetAppId, targetFormId, targetMenuId, targetBusinessType, targetSaasMark, workflowAddVO.getWorkflowId(),
                rightNodeCondition.getUid(), rightNodeCondition.getWrapperId(), memo, dataNodeCondition);
        nodeList.add(updateNode);
        nodeList.add(insertNode);
        workflowNodeModel.insertBatch(nodeList);
        if (Objects.isNull(wrapperUid)) {
            // 如果无触发条件时，则需要以当前节点的UId为上一个节点uid
            prevId = wrapperNodeCondition.getUid();
        } else {
            // 如果有触发条件时，则需要以当前整个条件块为上一个节点uid
            prevId = wrapperUid;
        }
        return prevId;
    }

    /**
     * 插入删除数据节点
     * @param corpid 公司id
     * @param name 节点名称
     * @param condition 条件
     * @param formId 触发表单-表单id
     * @param businessType 触发表单-表单id
     * @param saasMark 触发表单-saas 标识
     * @param targetAppId 目标表单- 应用id
     * @param targetFormId 目标表单- 表单id
     * @param targetMenuId 目标表单- 菜单id
     * @param targetBusinessType 目标表单- 业务类型
     * @param targetSaasMark 目标表单- saas标识
     * @param prevId 上一节点id
     * @param wrapperUid 所属块id，可能为null
     * @param workflowAddVO 工作流属性
     * @param memo 备注
     * @return
     */
    private String insertDeleteNode(String corpid, String name, String condition, Long formId, Integer businessType, Integer saasMark, Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType,
                                    Integer targetSaasMark, String prevId, String wrapperUid, WorkflowAddVO workflowAddVO, String memo, Integer editedData
                                    ) {
        WorkflowNodeEntity dataNodeCondition = getMultiDataNode(corpid, name, condition,  formId, businessType, saasMark,  workflowAddVO.getWorkflowNodeId(),targetAppId, targetFormId, targetMenuId, targetBusinessType, targetSaasMark,
                workflowAddVO.getWorkflowId(), prevId, wrapperUid, editedData);
        workflowNodeModel.insert(dataNodeCondition);
        DeleteRecordNode deleteRecordNode = new DeleteRecordNode();
        deleteRecordNode.setTriggerNodeFlag(0);
        deleteRecordNode.setWorkflowNodeId(dataNodeCondition.getId());
        WorkflowNodeEntity rightNodeCondition = new WorkflowNodeEntity(corpid, name, WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.DELETE_NODE.getType(),
                targetAppId, targetFormId, targetMenuId, targetSaasMark, targetBusinessType,
                workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), dataNodeCondition.getUid(), wrapperUid, 2, JSON.toJSONString(deleteRecordNode), memo);
        workflowNodeModel.insert(rightNodeCondition);
        if (Objects.isNull(wrapperUid)) {
            prevId = rightNodeCondition.getUid();
        }else {
            prevId = wrapperUid;
        }
        return prevId;
    }

    /**
     * 插入新建数据节点
     * @param corpid
     * @param name
     * @param operator
     * @param formId
     * @param businessType
     * @param saasMark
     * @param targetAppId
     * @param targetFormId
     * @param targetMenuId
     * @param targetBusinessType
     * @param targetSaasMark
     * @param prevId
     * @param wrapperUid
     * @param workflowAddVO
     * @param activeType
     * @param memo
     * @return
     */
    private String insertAddNode(String corpid, String name, String operator, Long formId, Integer businessType, Integer saasMark,
                                 Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType,
                                 Integer targetSaasMark, String prevId, String wrapperUid, WorkflowAddVO workflowAddVO, Integer activeType,
                                 String memo, WorkflowNodeEntity dataNode, Integer editedData) {
        // 解析操作转化成工作流的更新字段
        List<WorkflowOperationsPojo> operations = getOperatorList(operator, formId, businessType, saasMark, workflowAddVO.getWorkflowNodeId(), activeType, dataNode);

        InsertRecordNode insertRecordNode = new InsertRecordNode();
        insertRecordNode.setChooseDataSource(1);
        insertRecordNode.setOperations(operations);
        insertRecordNode.setEditedData(editedData);
        // 插入新建数据节点
        WorkflowNodeEntity insertNode = new WorkflowNodeEntity(corpid, name, WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CREATE_NODE.getType(),
                targetAppId, targetFormId, targetMenuId, targetSaasMark, targetBusinessType,
                workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), prevId, wrapperUid, null, JSON.toJSONString(insertRecordNode), memo);
        workflowNodeModel.insert(insertNode);
        if (Objects.isNull(wrapperUid)) {
            prevId = insertNode.getUid();
        }else {
            prevId = wrapperUid;
        }
        return prevId;
    }

    /**
     * 插入更新节点
     * @param corpid 公司id
     * @param name 节点名称
     * @param condition 过滤条件
     * @param operator 操作
     * @param formId 触发表单-表单id
     * @param businessType 触发表单-表单id
     * @param saasMark 触发表单-表单id
     * @param targetAppId 更新表单-表单id
     * @param targetFormId 更新表单-表单id
     * @param targetMenuId 更新表单-表单id
     * @param targetBusinessType 更新表单-表单id
     * @param targetSaasMark 更新表单-表单id
     * @param prevId 上一节点uid
     * @param wrapperUid 所属节点块id
     * @param workflowAddVO 工作流的id和起始节点的id
     * @param activeType 高级版，简易版
     * @param memo 备注
     * @return
     */
    private String insertUpdateNode(String corpid, String name, String condition, String operator, Long formId, Integer businessType, Integer saasMark,
                                    Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType,
                                    Integer targetSaasMark, String prevId, String wrapperUid, WorkflowAddVO workflowAddVO, Integer activeType, String memo, Integer editedData) {
        // 1.将过滤条件转化成获取多条数据节点
        WorkflowNodeEntity dataNodeCondition =  getMultiDataNode(corpid, name, condition, formId, businessType, saasMark, workflowAddVO.getWorkflowNodeId(),
                targetAppId, targetFormId, targetMenuId, targetBusinessType, targetSaasMark,
                 workflowAddVO.getWorkflowId(), prevId, wrapperUid, editedData);
        workflowNodeModel.insert(dataNodeCondition);
        // 2. 将更新字段转化成更新数据节点
        WorkflowNodeEntity insertNode = getUpdateNode(corpid, dataNodeCondition.getId(), operator, formId, businessType, saasMark, workflowAddVO.getWorkflowNodeId(), activeType,
                name, targetAppId, targetFormId,  targetMenuId,  targetBusinessType, targetSaasMark, workflowAddVO.getWorkflowId(), dataNodeCondition.getUid(), wrapperUid, memo, dataNodeCondition, editedData);

        workflowNodeModel.insert(insertNode);
        if (Objects.isNull(wrapperUid)) {
            prevId = insertNode.getUid();
        }else {
            prevId = wrapperUid;
        }
        return prevId;
    }
    /**
     * 插入前置条件
     * @param corpid
     * @param prevId
     * @param preCondition
     * @param formId
     * @param saasMark
     * @param businessType
     * @param workflowAddVO
     * @return
     */
    private WorkflowNodeEntity insertPreCondition(String corpid, String prevId, List<FilterConditionsPoJo> preCondition, Long formId, Integer saasMark, Integer businessType,  WorkflowAddVO workflowAddVO) {
        String wrapperUid = UUID.randomUUID().toString();
        WorkflowNodeEntityExt wrapperNodeCondition = new WorkflowNodeEntityExt(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), wrapperUid, prevId, null, null, JSON.toJSONString(new JSONObject()));
        WorkflowJointConditionPojo conditions = new WorkflowJointConditionPojo();
        conditions.setOperator(WorkflowConditionOperatorEnum.AND.getAlias());

        List<WorkflowConditionFilters> filters = new ArrayList<>();
        WorkflowConditionFilters workflowConditionFilters = new WorkflowConditionFilters();
        workflowConditionFilters.setOperator(WorkflowConditionOperatorEnum.AND.getAlias());

        List<WorkflowConditionPojo> filter = new ArrayList<>();
        preCondition.forEach(conditionsPoJo -> {
            List<Object> valueList = new ArrayList<>();
            if (conditionsPoJo.getValue() instanceof List) {
                valueList = JSON.parseArray(JSON.toJSONString(conditionsPoJo.getValue()), Object.class);
            } else {
                valueList.add(conditionsPoJo.getValue());
            }
            WorkflowConditionPojo filterCondition = new WorkflowConditionPojo(conditionsPoJo.getFieldType(), conditionsPoJo.getAttr(), 1, workflowAddVO.getWorkflowNodeId(),
                    formId, saasMark, businessType, conditionsPoJo.getSymbol(), conditionsPoJo.getValueType(), valueList);
            filter.add(filterCondition);
        });
        workflowConditionFilters.setFilter(filter);

        filters.add(workflowConditionFilters);

        conditions.setFilters(filters);


        ConditionNode conditionNode = new ConditionNode();
        conditionNode.setConditions(conditions);
        conditionNode.setType(ConditionTypeEnum.GENERAL_CONDITION.getType());
        conditionNode.setConditionType(WorkflowNodeConditionTypeEnum.NORMAL_TYPE.getType());
        WorkflowNodeEntityExt leftNodeCondition = new WorkflowNodeEntityExt(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), wrapperUid, wrapperUid, 1, JSON.toJSONString(conditionNode));
        // 右边的条件
        ConditionNode rightConditionNode = new ConditionNode();
        rightConditionNode.setType(ConditionTypeEnum.GENERAL_CONDITION.getType());
        rightConditionNode.setConditionType(WorkflowNodeConditionTypeEnum.NORMAL_TYPE.getType());
        WorkflowNodeEntityExt rightNodeCondition = new WorkflowNodeEntityExt(corpid, "", WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CONDITION_NODE.getType(),
                0L, 0L, 0L, 0, 0, workflowAddVO.getWorkflowId(), UUID.randomUUID().toString(), wrapperUid, wrapperUid, 2, JSON.toJSONString(rightConditionNode));
        List<WorkflowNodeEntityExt> nodeList = new ArrayList<>();
        nodeList.add(wrapperNodeCondition);
        nodeList.add(leftNodeCondition);
        nodeList.add(rightNodeCondition);
        workflowNodeModel.insertExtBatch(nodeList);
        return leftNodeCondition;
    }

    /**
     * 获取工作流的操作方式
     * @param operators 操作方式
     * @param formId
     * @param businessType
     * @param saasMark
     * @param startNodeId 起始节点id
     * @param versionType 高级版还是简易版
     * @return
     */
    private List<WorkflowOperationsPojo> getOperatorList(String operators, Long formId, Integer businessType, Integer saasMark, Long startNodeId, Integer versionType, WorkflowNodeEntity dataNode) {
        List<WorkflowOperationsPojo> operations = new ArrayList<>();
        List<OperationsPojo> operationsPojos = JSON.parseArray(operators, OperationsPojo.class);
        Map<String, String> formulaMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        String selfKey = formId.toString();
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType)) {
            selfKey = PaasConstant.WORK_ORDER + selfKey;
        }
        formulaMap.put("self","1."+startNodeId+"."+selfKey );
        if (Objects.nonNull(dataNode)) {
            String key = dataNode.getFormId().toString();
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), dataNode.getBusinessType())) {
                key = PaasConstant.WORK_ORDER + key;
            }
            formulaMap.put(key,"0."+dataNode.getId()+"."+ key );
        }
        operationsPojos.forEach(operationsPojo -> {
            FormulaPoJo formulaPoJo = operationsPojo.getFormulaInfo();
            Integer valueType = operationsPojo.getValueType();
            Integer triggerNodeFlag = 0;
            if (Objects.equals(versionType, RuleVersionEnum.ADVANCED.getType())) {
                // 公式版，将公式转行成最新的格式
                valueType = WorkflowValueTypeEnum.FORMULA.getType();
                formulaMap.forEach((index, value)->{
                   String formula = formulaPoJo.getFormula().replace(index, value);
                   formulaPoJo.setFormula(formula);
                });
            }
            if (Objects.equals(RuleValueTypeEnum.DYNAMIC_VALUE.getType(), 1)) {
                triggerNodeFlag = 1;
            }
            WorkflowOperationsPojo workflowOperationsPojo = new WorkflowOperationsPojo(startNodeId, formId, businessType, saasMark, triggerNodeFlag,
                    operationsPojo.getAttr(), operationsPojo.getAttrName(), operationsPojo.getFieldType(), operationsPojo.getSymbol(), valueType, operationsPojo.getValue(),
                    operationsPojo.getValueAttr(), operationsPojo.getValueFieldType(), operationsPojo.getValueAttrName(), formulaPoJo);
            operations.add(workflowOperationsPojo);
        });
        return operations;
    }


    private WorkflowNodeEntity getUpdateNode(String corpid, Long workflowNodeId, String operators, Long formId, Integer businessType, Integer saasMark, Long startNodeId, Integer activeType,
                                             String name, Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType, Integer targetSaasMark, Long workflowId,
                                             String prevId, String wrapperUid, String memo, WorkflowNodeEntity dataNode, Integer editedData) {
        UpdateRecordNode updateRecordNode = new UpdateRecordNode();
        updateRecordNode.setWorkflowNodeId(workflowNodeId);
        updateRecordNode.setTriggerNodeFlag(0);
        updateRecordNode.setEditedData(editedData);
        List<WorkflowOperationsPojo> operations = getOperatorList( operators, formId, businessType, saasMark, startNodeId, activeType, dataNode);
        updateRecordNode.setOperations(operations);
        WorkflowNodeEntity insertNode = new WorkflowNodeEntity(corpid, name, WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.UPDATE_NODE.getType(),
                targetAppId, targetFormId, targetMenuId, targetSaasMark, targetBusinessType, workflowId,
                UUID.randomUUID().toString(), prevId, wrapperUid, null, JSON.toJSONString(updateRecordNode), memo);
        return insertNode;
    }

    /**
     *
     * @param corpid
     * @param operators
     * @param formId
     * @param businessType
     * @param saasMark
     * @param startNodeId
     * @param activeType
     * @param name
     * @param targetAppId
     * @param targetFormId
     * @param targetMenuId
     * @param targetBusinessType
     * @param targetSaasMark
     * @param workflowId
     * @param prevId
     * @param wrapperUid
     * @param memo
     * @return
     */
    private WorkflowNodeEntity getInsertNode(String corpid, String operators, Long formId, Integer businessType, Integer saasMark, Long startNodeId, Integer activeType,
                                             String name, Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType, Integer targetSaasMark, Long workflowId,
                                             String prevId, String wrapperUid, String memo, WorkflowNodeEntity dataNode) {
        List<WorkflowOperationsPojo> operations = getOperatorList( operators, formId, businessType, saasMark, startNodeId, activeType, dataNode);

        InsertRecordNode insertRecordNode = new InsertRecordNode();
        insertRecordNode.setChooseDataSource(1);
        insertRecordNode.setOperations(operations);
        WorkflowNodeEntity insertNode = new WorkflowNodeEntity(corpid, name, WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.CREATE_NODE.getType(),
                targetAppId, targetFormId, targetMenuId, targetSaasMark, targetBusinessType, workflowId, UUID.randomUUID().toString(), prevId, wrapperUid, null,
                JSON.toJSONString(insertRecordNode), memo);
        return insertNode;
    }


    /**
     * 获取数据节点
     * @param corpid 公司id
     * @param name 节点名称
     * @param condition 条件
     * @param formId 触发表单-表单id
     * @param businessType 触发表单-表单id
     * @param saasMark 触发表单的标识
     * @param startNodeId 开始节点
     * @param targetAppId 执行表单/目标表单-应用id
     * @param targetFormId 执行表单/目标表单-表单id
     * @param targetMenuId 执行表单/目标表单-菜单id
     * @param targetBusinessType 执行表单/目标表单-业务类型
     * @param targetSaasMark 执行表单/目标表单-saas标识
     * @param workflowId 工作流id
     * @param prevId 上一个节点uid
     * @param wrapperUid 当前节点属于的块uid
     * @return
     */
    private WorkflowNodeEntity getMultiDataNode(String corpid, String name, String condition, Long formId, Integer businessType, Integer saasMark, Long startNodeId,
                                                Long targetAppId, Long targetFormId, Long targetMenuId, Integer targetBusinessType, Integer targetSaasMark,
                                            Long workflowId, String prevId, String wrapperUid, Integer editedData) {
        List<FilterCondition> conditionList = new ArrayList<>();
        List<FilterConditionsPoJo> filterConditionsPoJos = JSON.parseArray(condition, FilterConditionsPoJo.class);
        filterConditionsPoJos.forEach(filterConditionsPoJo -> {
            FilterCondition filterCondition = new FilterCondition(0, filterConditionsPoJo.getAttr(), filterConditionsPoJo.getFieldType(), filterConditionsPoJo.getAttrName(), filterConditionsPoJo.getSymbol(),
                    filterConditionsPoJo.getValueType(), filterConditionsPoJo.getValue(), filterConditionsPoJo.getValueAttr(), filterConditionsPoJo.getValueFieldType(), filterConditionsPoJo.getValueAttrName(),
                    filterConditionsPoJo.getRel());
            if (Objects.equals(RuleValueTypeEnum.DYNAMIC_VALUE.getType(), filterConditionsPoJo.getValueType())) {
                filterCondition = new FilterCondition(saasMark, businessType, formId, startNodeId, 1, filterConditionsPoJo.getAttr(), filterConditionsPoJo.getFieldType(), filterConditionsPoJo.getAttrName(), filterConditionsPoJo.getSymbol(),
                        filterConditionsPoJo.getValueType(), filterConditionsPoJo.getValue(), filterConditionsPoJo.getValueAttr(), filterConditionsPoJo.getValueFieldType(), filterConditionsPoJo.getValueAttrName(),
                        filterConditionsPoJo.getRel());
            }
            conditionList.add(filterCondition);
        });
        ObtainMultiDataNode obtainMultiDataNode = new ObtainMultiDataNode();
        obtainMultiDataNode.setDataSources(1);
        obtainMultiDataNode.setFilterCondition(conditionList);
        obtainMultiDataNode.setExceedLimitDataEvent(2);
        obtainMultiDataNode.setNoDataEvent(1);
        obtainMultiDataNode.setEditedData(editedData);

        WorkflowNodeEntity dataNodeCondition = new WorkflowNodeEntity(corpid, name, WorkflowTriggerMethodEnum.FORM.getType(), WorkflowNodeTypeEnum.MULTI_DATA_NODE.getType(),
                targetAppId, targetFormId, targetMenuId, targetSaasMark, targetBusinessType,   workflowId,
                UUID.randomUUID().toString(), prevId, wrapperUid, null, JSON.toJSONString(obtainMultiDataNode), "");
        return dataNodeCondition;
    }

    /**
     * 获取起始节点
     * @param businessRuleInfoEntity
     * @param triggerType
     * @return
     */
    private WorkflowNodePojo getStartNode(BusinessRuleInfoEntity businessRuleInfoEntity, Integer triggerType) {
        WorkflowNodePojo workflowNodePojo = new WorkflowNodePojo();
        workflowNodePojo.setNodeId("startNode");
        workflowNodePojo.setPrevId("0");
        workflowNodePojo.setAppId(businessRuleInfoEntity.getAppId());
        workflowNodePojo.setMenuId(businessRuleInfoEntity.getMenuId());
        workflowNodePojo.setFormId(businessRuleInfoEntity.getFormId());
        workflowNodePojo.setSaasMark(businessRuleInfoEntity.getSaasMark());
        workflowNodePojo.setBusinessType(businessRuleInfoEntity.getBusinessType());
        workflowNodePojo.setName("触发节点");
        workflowNodePojo.setTriggerType(WorkflowTriggerMethodEnum.FORM.getType());
        workflowNodePojo.setType(WorkflowNodeTypeEnum.START_NODE.getType());
        workflowNodePojo.setUsePermission(0);
        WorkflowNodeCoreConfiguration workflowNodeCoreConfiguration = new WorkflowNodeCoreConfiguration();
        FormTriggerNode formTriggerNode = new FormTriggerNode();
        formTriggerNode.setFieldPermission(new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
        formTriggerNode.setNeedApproveFields(new ArrayList<>());
        formTriggerNode.setTitleList(new ArrayList<>());
        formTriggerNode.setTriggerConditions(new ArrayList<>());
        formTriggerNode.setType(triggerType);
        workflowNodeCoreConfiguration.setFormTriggerNode(formTriggerNode);
        workflowNodePojo.setCoreConfiguration(workflowNodeCoreConfiguration);
        return workflowNodePojo;
    }

    /**
     * Description: 工作流模板数据还原
     * @param fixDataJobDTO
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2021/11/16 21:22
     * @since
     */
    public void workflowBack(FixDataJobDTO fixDataJobDTO) throws XbbException {
        String corpid = fixDataJobDTO.getCorpid();

        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        List<Integer> businessTypeList = fixDataJobDTO.getBusinessTypeList();
        if (CollectionsUtil.isNotEmpty(businessTypeList)) {
            Map<String, Object> param = new HashMap<>();
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            for (Integer businessType : businessTypeList) {

                param.put("businessType", businessType);

                log.warn(XbbRefTypeEnum.getByCode(businessType).getName() + "工作流模板数据开始还原, businessType= " + businessType);
                List<PaasProcessMigrationEntity> paasProcessMigrationEntities = paasProcessMigrationModel.findEntitys(param);

                List<Long> workflowIds = new ArrayList<>();
                paasProcessMigrationEntities.forEach(v -> workflowIds.add(v.getWorkflowId()));
                if (CollectionsUtil.isNotEmpty(workflowIds)) {
                    workflowModel.deleteBatch(workflowIds, corpid);
                    workflowNodeModel.deleteByWorkflowId(workflowIds, corpid);
                }
            }

        } else if (CollectionsUtil.isNotEmpty(dataIdList)) {
            workflowModel.deleteBatch(dataIdList, corpid);
            workflowNodeModel.deleteByWorkflowId(dataIdList, corpid);
        }

        log.warn("工作流模板数据还原结束，success");
    }
}
